Spotify Web APIでデバイスから指定した音楽を再生してみる
先日個人的にSpotifyを契約し、こちらでSpotify Web APIの使い方を読んだ後なんとなく公式のドキュメントを見ていたところ、情報の取得や更新に限らず音楽の再生ができるとのことでした。
本記事では、APIを実行する準備を行い、以下のようなシナリオでAPIを実行してみます。
- 接続されたデバイスの一覧を取得
- 自分のプレイリスト一覧の取得
- プレイリストに登録されたトラック一覧の取得
- デバイスを指定して、取得したトラックを再生
注意
一部ベータ版のAPIを呼び出しています。これらは予告なしに挙動が変わる可能性があるとのことです。 参考:New Endpoints (Beta): Web API Connect
前提条件
- Spotify Premiumに登録済みであること(Premiumユーザに生成されたトークンでしか実行できないエンドポイントがあります。)
- Spotifyでなんらかのプレイリストを登録していること
- aurlがインストール済みであること
やってみる
アプリケーションの登録
SpotifyにAPIを呼び出すアプリケーションを登録する必要があります。 ダッシュボードにログインし、CREATE A CLIENT IDからアプリケーションを登録します。
アプリケーションの概要を指定します。
登録後、Client IDおよびClient Secretが取得できるのでメモしておきます。
EDIT SETTINGSから設定を開き、Redirect URLsを指定します。今回はコマンドラインからAPIを実行するだけなので、とりあえずhttp://example.comとしておきます。
Spotify側の準備はこれで整いました。
aurlの準備
Spotify Web APIでは、OAuth2.0のAuthorization Code、Client Credentials、Implicit Grantのフローがそれぞれサポートされていますが、このうちClient Credentialsでは特定のユーザのリソースへのアクセスができないため、Authorization Code Flowでのアクセスをします。 コマンドを簡易にするため、本記事ではaurlを利用します。
aurlにSpotifyから認可コードおよびトークンを得るためのエンドポイントと必要なスコープ、アプリケーションの登録時に取得したclient_id,client_secretを指定します。
$ vi ~/.aurl/profiles [spotify] grant_type = authorization_code client_id = {$取得したCLIENT ID} client_secret = {$取得したCLIENT SECRET} auth_server_auth_endpoint = https://accounts.spotify.com/authorize auth_server_token_endpoint = https://accounts.spotify.com/api/token redirect = http://example.com scopes = user-read-playback-state,playlist-read-private,user-modify-playback-state
スコープはアプリケーションでやりたいことに合わせて指定する必要があります。 リファレンスにはエンドポイントごとに必要なスコープが記載されています。
APIの呼び出し
アクセストークンの取得とデバイス一覧の取得
先ほど指定した設定でデバイス一覧取得のAPIにアクセスします。
$ aurl --profile spotify https://api.spotify.com/v1/me/player/devices
初回のアクセス時はSpotify側のリソースへのアクセス権限の許可を求める画面が開くので、OKをクリックします。
以下のようなURLにリダイレクトしますので、クエリパラメータのcodeの値を取得します。
http://example.com/?code=xxxxx&state=xxxxx
コンソールに戻ります。認可コードの入力を求められるので、取得したcodeを指定します。
$ aurl --profile spotify https://api.spotify.com/v1/me/player/devices Open browser and get code from https://accounts.spotify.com/authorize?client_id=xxxxx&redirect_uri=http%3A%2F%2Fexample.com&response_type=code&scope=user-read-playback-state&state=xxxxx Enter code: XXXXXXXXXXXX { "devices" : [ { "id" : "xxxxx", "is_active" : false, "is_restricted" : false, "name" : "JunのMacBook Pro", "type" : "Computer", "volume_percent" : 100 }, { "id" : "xxxxx_google_home", "is_active" : true, "is_restricted" : false, "name" : "部屋", "type" : "CastAudio", "volume_percent" : null } ]
APIが実行され、登録済みのデバイス一覧が取得できました。今使っているPCと、部屋に置いてあるGoogle Homeが登録されています。(Google Homeに部屋という名前をつけています)
プレイリストの取得
登録済みのプレイリスト一覧を取得します。
$ aurl --profile spotify https://api.spotify.com/v1/me/playlists?limit=1 { "href" : "https://api.spotify.com/v1/users/xxxxx/playlists?offset=0&limit=1", "items" : [ { "collaborative" : false, "external_urls" : { "spotify" : "https://open.spotify.com/user/xxxxx/playlist/xxxxx" }, "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx", "id" : "xxxxx", "images" : [ { "height" : 640, "url" : "https://mosaic.scdn.co/640/4eb485bd0bdbf234199edc0572771a8fe730fa8e6b4b0822365b0bdbd3689028beceabc0afebdd81c5ea254b988b9a74b46dfc5aeb5cac0ed82a0ad7ef7b43e117090d33f2dd7364b9eedc2473595b81", "width" : 640 }, { "height" : 300, "url" : "https://mosaic.scdn.co/300/4eb485bd0bdbf234199edc0572771a8fe730fa8e6b4b0822365b0bdbd3689028beceabc0afebdd81c5ea254b988b9a74b46dfc5aeb5cac0ed82a0ad7ef7b43e117090d33f2dd7364b9eedc2473595b81", "width" : 300 }, { "height" : 60, "url" : "https://mosaic.scdn.co/60/4eb485bd0bdbf234199edc0572771a8fe730fa8e6b4b0822365b0bdbd3689028beceabc0afebdd81c5ea254b988b9a74b46dfc5aeb5cac0ed82a0ad7ef7b43e117090d33f2dd7364b9eedc2473595b81", "width" : 60 } ], "name" : "Footwork-Jungle-Juke", "owner" : { "display_name" : "xxxxx", "external_urls" : { "spotify" : "https://open.spotify.com/user/xxxxx" }, "href" : "https://api.spotify.com/v1/users/xxxxx", "id" : "xxxxx", "type" : "user", "uri" : "spotify:user:xxxxx" }, "public" : false, "snapshot_id" : "EhO8zMMM43/IsIAuTnNNN06ByyJTwsyW2upGErVE478dw/IH6P5ogZGEr9nm0wvv", "tracks" : { "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks", "total" : 87 }, "type" : "playlist", "uri" : "spotify:user:xxxxx:playlist:xxxxx" } ], "limit" : 1, "next" : "https://api.spotify.com/v1/users/xxxxx/playlists?offset=1&limit=1", "offset" : 0, "previous" : null, "total" : 8 }
プレイリスト内のトラックの取得
プレイリストに登録されているトラックを取得します。
$ aurl --profile spotify https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?limit=1 { "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=0&limit=1", "items" : [ { "added_at" : "2016-04-21T07:14:13Z", "added_by" : { "external_urls" : { "spotify" : "https://open.spotify.com/user/xxxxx" }, "href" : "https://api.spotify.com/v1/users/xxxxx", "id" : "xxxxx", "type" : "user", "uri" : "spotify:user:xxxxx" }, "is_local" : false, "track" : { "album" : { "album_type" : "album", "artists" : [ { "external_urls" : { "spotify" : "https://open.spotify.com/artist/4zGBj9dI63YIWmZkPl3o7V" }, "href" : "https://api.spotify.com/v1/artists/4zGBj9dI63YIWmZkPl3o7V", "id" : "4zGBj9dI63YIWmZkPl3o7V",f "name" : "DJ Rashad", "type" : "artist", "uri" : "spotify:artist:4zGBj9dI63YIWmZkPl3o7V" } ], "available_markets" : [ ], "external_urls" : { "spotify" : "https://open.spotify.com/album/4J7qkorMbPmJQy79SntDA8" }, "href" : "https://api.spotify.com/v1/albums/4J7qkorMbPmJQy79SntDA8", "id" : "4J7qkorMbPmJQy79SntDA8", "images" : [ { "height" : 640, "url" : "https://i.scdn.co/image/9cf0d76e58f1cdb75d209891a4ab66c653e3647a", "width" : 640 }, { "height" : 300, "url" : "https://i.scdn.co/image/fe38654a0e5a01772b3ba4c351b23ce2d687102b", "width" : 300 }, { "height" : 64, "url" : "https://i.scdn.co/image/d6c1a2d7c49bacba6f42d8138a99d41a17befb05", "width" : 64 } ], "name" : "Double Cup", "release_date" : "2013-10-22", "release_date_precision" : "day", "type" : "album", "uri" : "spotify:album:4J7qkorMbPmJQy79SntDA8" }, "artists" : [ { "external_urls" : { "spotify" : "https://open.spotify.com/artist/4zGBj9dI63YIWmZkPl3o7V" }, "href" : "https://api.spotify.com/v1/artists/4zGBj9dI63YIWmZkPl3o7V", "id" : "4zGBj9dI63YIWmZkPl3o7V", "name" : "DJ Rashad", "type" : "artist", "uri" : "spotify:artist:4zGBj9dI63YIWmZkPl3o7V" }, { "external_urls" : { "spotify" : "https://open.spotify.com/artist/238R2QkXhYWy3YUIYlbtsc" }, "href" : "https://api.spotify.com/v1/artists/238R2QkXhYWy3YUIYlbtsc", "id" : "238R2QkXhYWy3YUIYlbtsc", "name" : "Spinn", "type" : "artist", "uri" : "spotify:artist:238R2QkXhYWy3YUIYlbtsc" } ], "available_markets" : [ ], "disc_number" : 1, "duration_ms" : 270813, "explicit" : false, "external_ids" : { "isrc" : "GBLZC1300093" }, "external_urls" : { "spotify" : "https://open.spotify.com/track/3Sb3FlaHxs5UYVukCy5oNW" }, "href" : "https://api.spotify.com/v1/tracks/3Sb3FlaHxs5UYVukCy5oNW", "id" : "3Sb3FlaHxs5UYVukCy5oNW", "name" : "Feelin (feat. Spinn & Taso)", "popularity" : 24, "preview_url" : null, "track_number" : 1, "type" : "track", "uri" : "spotify:track:3Sb3FlaHxs5UYVukCy5oNW" } } ], "limit" : 1, "next" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=1&limit=1", "offset" : 0, "previous" : null, "total" : 87 }
取得できました。しかしこのトラックはSpotifyアプリのプレイリストには表示されず再生することもできません。
地域によってSpotifyで配信されている曲は異なるのですが、日本で設定されているアカウントはavailable_marketsにJPが含まれているものだけが再生可能です。
ページ送り
JPで再生可能なトラックを探してみます。
$ aurl --profile spotify "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?limit=1&offset=15" { "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=15&limit=1", "items" : [ { "added_at" : "2016-04-21T07:35:39Z", "added_by" : { "external_urls" : { "spotify" : "https://open.spotify.com/user/xxxxx" }, "href" : "https://api.spotify.com/v1/users/xxxxx", "id" : "xxxxx", "type" : "user", "uri" : "spotify:user:xxxxx" }, "is_local" : false, "track" : { "album" : { "album_type" : "single", "artists" : [ { "external_urls" : { "spotify" : "https://open.spotify.com/artist/7DF6NrPDuqT69SYiqtWWcW" }, "href" : "https://api.spotify.com/v1/artists/7DF6NrPDuqT69SYiqtWWcW", "id" : "7DF6NrPDuqT69SYiqtWWcW", "name" : "Stray", "type" : "artist", "uri" : "spotify:artist:7DF6NrPDuqT69SYiqtWWcW" } ], "available_markets" : [ "AD", "AR", "AT", "AU", "BE", "BG", "BO", "BR", "CA", "CH", "CL", "CO", "CR", "CY", "CZ", "DE", "DK", "DO", "EC", "EE", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN", "HU", "ID", "IE", "IL", "IS", "IT", "JP", "LI", "LT", "LU", "LV", "MC", "MT", "MX", "MY", "NI", "NL", "NO", "NZ", "PA", "PE", "PH", "PL", "PT", "PY", "RO", "SE", "SG", "SK", "SV", "TH", "TR", "TW", "US", "UY", "VN", "ZA" ], "external_urls" : { "spotify" : "https://open.spotify.com/album/6FfCvbzYiemvMq3XhUs6S0" }, "href" : "https://api.spotify.com/v1/albums/6FfCvbzYiemvMq3XhUs6S0", "id" : "6FfCvbzYiemvMq3XhUs6S0", "images" : [ { "height" : 640, "url" : "https://i.scdn.co/image/1ce4d8afcc725e19b036870b38d6632275548221", "width" : 640 }, { "height" : 300, "url" : "https://i.scdn.co/image/4d04b1ba0e40bc695545739ae787f86693e293c7", "width" : 300 }, { "height" : 64, "url" : "https://i.scdn.co/image/32baf422c32ad7e5ec95e4a2088da3601d75b105", "width" : 64 } ], "name" : "Paradise (Remixes)", "release_date" : "2015-07-31", "release_date_precision" : "day", "type" : "album", "uri" : "spotify:album:6FfCvbzYiemvMq3XhUs6S0" }, "artists" : [ { "external_urls" : { "spotify" : "https://open.spotify.com/artist/7DF6NrPDuqT69SYiqtWWcW" }, "href" : "https://api.spotify.com/v1/artists/7DF6NrPDuqT69SYiqtWWcW", "id" : "7DF6NrPDuqT69SYiqtWWcW", "name" : "Stray", "type" : "artist", "uri" : "spotify:artist:7DF6NrPDuqT69SYiqtWWcW" }, { "external_urls" : { "spotify" : "https://open.spotify.com/artist/06xa1OLBsMQJFXcl2tQkH4" }, "href" : "https://api.spotify.com/v1/artists/06xa1OLBsMQJFXcl2tQkH4", "id" : "06xa1OLBsMQJFXcl2tQkH4", "name" : "Machinedrum", "type" : "artist", "uri" : "spotify:artist:06xa1OLBsMQJFXcl2tQkH4" } ], "available_markets" : [ "AD", "AR", "AT", "AU", "BE", "BG", "BO", "BR", "CA", "CH", "CL", "CO", "CR", "CY", "CZ", "DE", "DK", "DO", "EC", "EE", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN", "HU", "ID", "IE", "IL", "IS", "IT", "JP", "LI", "LT", "LU", "LV", "MC", "MT", "MX", "MY", "NI", "NL", "NO", "NZ", "PA", "PE", "PH", "PL", "PT", "PY", "RO", "SE", "SG", "SK", "SV", "TH", "TR", "TW", "US", "UY", "VN", "ZA" ], "disc_number" : 1, "duration_ms" : 278120, "explicit" : false, "external_ids" : { "isrc" : "GBSZM1500364" }, "external_urls" : { "spotify" : "https://open.spotify.com/track/0ipvRATjnKeAlIRNS5WqhN" }, "href" : "https://api.spotify.com/v1/tracks/0ipvRATjnKeAlIRNS5WqhN", "id" : "0ipvRATjnKeAlIRNS5WqhN", "name" : "Movements - Machinedrum Remix", "popularity" : 10, "preview_url" : "https://p.scdn.co/mp3-preview/7d31cf6f2685552ab64ad6d9151748e30a7cdeea?cid=866fa1fcd099495ea671e5d52b655dd7", "track_number" : 2, "type" : "track", "uri" : "spotify:track:0ipvRATjnKeAlIRNS5WqhN" } } ], "limit" : 1, "next" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=16&limit=1", "offset" : 15, "previous" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=14&limit=1", "total" : 87 }
こちらは再生可能なようです。Spotifyアプリ上にも表示されます。
再生する
以下のAPIで音楽を再生できます。 urisが配列なのは、次に再生する曲、さらに次に再生する曲、を指定できるためです。
aurl --profile spotify -X PUT https://api.spotify.com/v1/me/player/play?device_id=xxxxx_google_home -d '{"uris":["spotify:track:0ipvRATjnKeAlIRNS5WqhN", "spotify:track:4TzkNDcjO1wiaRYs2HLXvA"]}'
Google Homeから音楽が再生されました。また、2番目に登録したトラックもPlay Queueに登録されています。
停止する
以下のAPIで再生中のトラックが停止します。
aurl --profile spotify -X PUT https://api.spotify.com/v1/me/player/pause?device_id=xxxxx_google_home
まとめ
- Spotify Web APIによって、以下の操作をしてみました。
- 接続済みのデバイス一覧の取得
- 登録済みのプレイリストの取得
- プレイリスト内のトラック一覧の取得
- 指定したトラックの再生と停止
- 一部ベータ版のAPIを呼び出しています。これらは予告なしに挙動が変わる可能性があるとのことです。
とりあえず指定した時刻に指定したプレイリストからランダムで音楽が流れるアプリ(≒目覚めし時計)を作ってみようかなという気分です。
私からは以上です。